using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using backend.Common;
using backend.Models.Dtos;
using backend.Repositories;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Services;

namespace backend.Controllers
{
    [EnableCors]
    [ApiController]
    [Route("/api/orders")]
    public class RepairOrderController : ControllerBase
    {
        private readonly RepairRequestRepo _repairRequestRepo;
        private readonly ILogger<RepairOrderController> _logger;

        public RepairOrderController(ILogger<RepairOrderController> logger, RepairRequestRepo repo)
        {
            _repairRequestRepo = repo;
            _logger = logger;
        }

        /// <summary>
        /// 创建一个新的维修工单。
        /// </summary>
        /// <param name="dto">创建工单所需的DTO对象。</param>
        /// <returns>创建成功的工单或错误信息。</returns>
        [HttpPost]
        public async Task<IActionResult> CreateOrderAsync([FromForm] RepairRequestCreateDto dto)
        {
            try
            {
                // 模型验证
                if (!ModelState.IsValid)
                {
                    return BadRequest(new { code = "failure", description = "parameter not valid" });
                }

                // 创建工单
                var repairRequest = await _repairRequestRepo.CreateRepairRequestAsync(dto);
                if (repairRequest == null)
                {
                    return BadRequest(new { code = "failure", description = "Failed to create repair request." });
                }

                return Ok(new { code = "success" });
            }
            catch (Exception ex)
            {
                return BadRequest(new { code = "failure", description = ex.Message });
            }
        }

        [HttpGet("{orderId}")]
        public async Task<IActionResult> GetRepairRequestDetails(int orderId)
        {
            try
            {
                var repairRequestDto = await _repairRequestRepo.GetRepairRequestByIdAsync(orderId);

                if (repairRequestDto == null)
                {
                    return NotFound(new { code = "failure", description = "Order not found." });
                }

                var response = new
                {
                    code = "success",
                    data = repairRequestDto
                };

                return Ok(response);
            }
            catch (ArgumentException ex)
            {
                _logger.LogError(ex, "Failed to retrieve order details.");
                return BadRequest(new { code = "failure", description = ex.Message });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "An unexpected error occurred while retrieving order details.");
                return StatusCode(500, new { code = "failure", description = "Internal server error." });
            }
        }

        [HttpGet]
        public async Task<IActionResult> GetRepairRequestList([FromQuery] int page = 1, [FromQuery] int number = 10, [FromQuery] string? specialize = null, [FromQuery] string? area = null, [FromQuery] string? status = null)
        {
            try
            {
                var principal = JwtHelper.GetAndValidateJwtToken(Request);
                if (principal == null)
                {
                    return StatusCode(401, new { code = "failure", description = "Unauthorized" });
                }

                var userID = principal.UserId;
                var role = principal.Role;

                if (string.IsNullOrEmpty(userID) || string.IsNullOrEmpty(role))
                {
                    return Unauthorized(new { code = "failure", description = "User ID or role not found in token." });
                }

                var repairRequestList = await _repairRequestRepo.GetRepairRequestListAsync(page, number, specialize, userID, role, area, status);

                var response = new
                {
                    code = "success",
                    data = repairRequestList
                };

                return Ok(response);
            }
            catch (ArgumentException ex)
            {
                _logger.LogError(ex, "Failed to retrieve repair request list.");
                return BadRequest(new { code = "failure", description = ex.Message });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "An unexpected error occurred while retrieving repair request list.");
                return StatusCode(500, new { code = "failure", description = "Internal server error." });
            }
        }

        [HttpPatch("{orderID}")]
        public async Task<IActionResult> UpdateRepairRequest(int orderID, [FromBody] RepairRequestUpdateDto dto)
        {
            var principal = JwtHelper.GetAndValidateJwtToken(Request);
            if (principal == null)
            {
                return StatusCode(401, new { code = "failure", description = "Unauthorized" });
            }

            var userID = principal.UserId;
            var role = principal.Role;

            if (string.IsNullOrEmpty(userID) || string.IsNullOrEmpty(role))
            {
                return Unauthorized(new { code = "failure", description = "User ID or role not found in token." });
            }

            if (!Enum.TryParse<UserRole>(role, out UserRole userRole))
            {
                return BadRequest("Invalid user role provided.");
            }

            try
            {
                var result = await _repairRequestRepo.UpdateRepairRequestAsync(orderID, userRole, userID,dto.Status, dto.Rating, dto.Evaluate);
                if (result) { return Ok(new { code = "success" }); } else { return Ok(new { code = "failure", description = "can't update repair request." }); }
            }
            catch (KeyNotFoundException e)
            {
                return NotFound(e.Message);
            }
            catch (Exception e)
            {
                return StatusCode(StatusCodes.Status500InternalServerError, e.Message);
            }
        }
    }
}